﻿using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell.Interop;

namespace JH.GladeSharpCodeGenerator
{
    [ComVisible(true)]
    public abstract class BaseCodeGenerator : IVsSingleFileGenerator
    {
        public int Generate(string wszInputFilePath, string bstrInputFileContents,
                            string wszDefaultNamespace, IntPtr[] rgbOutputFileContents,
                            out uint pcbOutput, IVsGeneratorProgress pGenerateProgress)
        {
            if (bstrInputFileContents == null)
            {
                throw new ArgumentNullException("bstrInputFileContents");
            }
            _codeFilePath = wszInputFilePath;
            _codeFileNamespace = wszDefaultNamespace;
            CodeGeneratorProgress = pGenerateProgress;
            var source = GenerateCode(bstrInputFileContents, wszInputFilePath);
            if (source == null)
            {
                rgbOutputFileContents[0] = IntPtr.Zero;
                pcbOutput = 0;
            }
            else
            {
                pcbOutput = (uint)source.Length;
                rgbOutputFileContents[0] = Marshal.AllocCoTaskMem((int)pcbOutput);
                Marshal.Copy(source, 0, rgbOutputFileContents[0], (int)pcbOutput);
            }
            return VSConstants.S_OK;
        }

        public abstract int DefaultExtension(out string pbstrDefaultExtension);

        protected abstract byte[] GenerateCode(string inputFileContent, string inputFileName);


        [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", 
            MessageId = "Microsoft.VisualStudio.Shell.Interop.IVsGeneratorProgress.GeneratorError(System.Int32,System.UInt32,System.String,System.UInt32,System.UInt32)",
            Justification = "If this call fails, there is nothing to do anyway.")]
        protected void GeneratorErrorCallback(bool warning, int level, string message, int line, int column)
        {
            var progress = CodeGeneratorProgress;
            if (progress != null)
                progress.GeneratorError(warning ? 1 : 0, (uint)level, message, (uint)line, (uint)column);
        }

        protected IVsGeneratorProgress CodeGeneratorProgress { get; set; }

        private string _codeFileNamespace = "";
        protected string FileNamespace
            { get { return _codeFileNamespace; } }

        private string _codeFilePath = "";
        protected string InputFilePath
            { get { return _codeFilePath; } }
    }
}
